﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using AutoLoL.Entities;
using AutoLoL.Logic.Exceptions;
using AutoLoL.Logic.Windows;
using AutoLoL.Shared;
using WindowsInput;
using Point = System.Drawing.Point;

namespace AutoLoL.Logic.Automation
{
    public class AutoClicker
    {
        // Maximum time to wait
        private const int WAIT_TIMER = 4;

        public static void Click(MasteryBuild masteryBuild, MASTERY_WINDOWS targetWindow = MASTERY_WINDOWS.None, bool manualReturn = false)
        {
            try
            {
                using (ClientWindow clientWindow = new ClientWindow())
                {
                    bool isTargetForced = (targetWindow != MASTERY_WINDOWS.None);

                    // Try and get focus
                    clientWindow.SetFocus();
                    Thread.Sleep(50);

                    // Block user input
                    Win32.BlockInput(true);

                    DateTime start = DateTime.Now;
                    while (true)
                    {
                        // If we got focus
                        if (clientWindow.IsForegroundWindow)
                        {
                            // Detect an open mastery window
                            if (!isTargetForced)
                            {
                                if (clientWindow.IsMasteriesOpen(MASTERY_WINDOWS.ChampionSelect))
                                {
                                    targetWindow = MASTERY_WINDOWS.ChampionSelect;
                                }
                                else if (clientWindow.IsMasteriesOpen(MASTERY_WINDOWS.UserProfile))
                                {
                                    targetWindow = MASTERY_WINDOWS.UserProfile;
                                }
                            }

                            // Continue if we detected a window or if one was forced
                            if (targetWindow != MASTERY_WINDOWS.None)
                            {
                                break;
                            }
                        }

                        // Throw an exception after {WAIT_TIMER} seconds
                        if ((DateTime.Now - start).TotalSeconds > WAIT_TIMER)
                        {
                            if (!clientWindow.IsForegroundWindow)
                            {
                                throw new WindowNotFocusableException();
                            }
                            else
                            {
                                throw new MasteriesNotDetectedException();
                            }
                        }

                        Thread.Sleep(50);
                    }

                    Console.WriteLine(targetWindow.ToString());

                    // NOTE - MouseSimulator.MoveMouseTo() does not work when input is blocked!
                    MouseSimulator simulator = new MouseSimulator();

                    // Click the return points button
                    Point returnPoint = clientWindow.GetReturnPointLocation(targetWindow);
                    Win32.SetCursorPos(returnPoint.X, returnPoint.Y);
                    simulator.LeftButtonClick();

                    // Give it some time to return points
                    // TODO - Try to create a check that detects if points are returned
                    Thread.Sleep(800);

                    // Do the magic
                    foreach (MasteryTree masteryTree in masteryBuild.MasteryTrees)
                    {
                        foreach (MasteryValue mastery in masteryTree.MasteryValues)
                        {
                            Point masteryPoint = clientWindow.GetMasteryLocation(targetWindow, mastery);

                            for (int i = 0; i < mastery.CurrentRank; i++)
                            {
                                // Make sure the masteries window is still open if the target was not forced
                                if (!isTargetForced)
                                {
                                    start = DateTime.Now;
                                    while (true)
                                    {
                                        if ((targetWindow == MASTERY_WINDOWS.UserProfile && clientWindow.IsMasteriesOpen(MASTERY_WINDOWS.UserProfile))
                                            || (targetWindow == MASTERY_WINDOWS.ChampionSelect && clientWindow.IsMasteriesOpen(MASTERY_WINDOWS.ChampionSelect)))
                                        {
                                            break;
                                        }

                                        // Throw an exception after {WAIT_TIMER} seconds
                                        if ((DateTime.Now - start).TotalSeconds > WAIT_TIMER)
                                        {
                                            throw new MasteriesNotDetectedException();
                                        }

                                        Thread.Sleep(50);
                                    }
                                }

                                // Click
                                Win32.SetCursorPos(masteryPoint.X, masteryPoint.Y);
                                simulator.LeftButtonClick();

                                // Wait a short time between clicks
                                Thread.Sleep(80);

                                // Reset the cursor to prevent the tooltip from showing
                                Win32.SetCursorPos((int)clientWindow.ClientRectangle.Left, (int)clientWindow.ClientRectangle.Top);
                            }
                        }
                    }

                    // Give it some time for the UI to keep up
                    Thread.Sleep(400);

                    // Release user input
                    Win32.BlockInput(false);
                }
            }
            catch (Exception ex1)
            {
                // Release user input
                Win32.BlockInput(false);

                if (Debugger.IsAttached) throw ex1; 
            }
        }
    }
}